<?php
declare (strict_types=1);

namespace ffhome\frame\service;

use ffhome\frame\model\AclDept;
use ffhome\frame\model\AclPermission;
use ffhome\frame\model\AclRole;
use ffhome\frame\model\AclRoleDept;
use ffhome\frame\model\AclRolePermission;
use ffhome\frame\model\AclUserRole;
use think\facade\Db;

/**
 * 权限验证服务（部门）
 * 在provider.php文件中增加'authService' => AuthDeptService::class,配置
 */
class AuthDeptService extends AuthService
{
    protected $sessionField = 'u.id,u.username,u.nickname,u.avatar,u.dept_id';

    public function checkDataScope($deptField, $userField, &$where = []): array
    {
        $condition = [];
        $user = authService()->currentUser();
        $scopes = $this->getDataScope($user['id'], authService()->currentNode());
        $DEPT = config('database.connections.' . config('database.default') . '.prefix') . AclDept::MODEL_NAME;
        foreach ($scopes as $scope) {
            if ($scope['data_scope'] == AclRole::DS_ALL) {
                //全部数据
                $condition = [];
                break;
            } else if ($scope['data_scope'] == AclRole::DS_CUSTOM) {
                //自定义部门数据
                $deptIds = Db::name(AclRoleDept::MODEL_NAME)->where('role_id', $scope['id'])
                    ->column('dept_id');
                $condition[] = "({$deptField} IN (" . implode(',', $deptIds) . "))";
            } else if ($scope['data_scope'] == AclRole::DS_DEPT) {
                //本部门数据
                $condition[] = "{$deptField}={$user['dept_id']}";
            } else if ($scope['data_scope'] == AclRole::DS_DEPT_AND_CHILD) {
                //本部门及以下数据
                $condition[] = "({$deptField} in (SELECT id FROM {$DEPT}"
                    . " WHERE id={$user['dept_id']} or find_in_set({$user['dept_id']},ancestors)))";
            } else if ($scope['data_scope'] == AclRole::DS_SELF) {
                //本人数据
                $condition[] = "{$userField}={$user['id']}";
            }
        }
        if (count($condition) > 0) {
            $where[] = Db::raw(implode(' or ', $condition));
        }
        return $condition;
    }

    private function getDataScope($userId, $node): array
    {
        return Db::name(AclPermission::MODEL_NAME)->alias('p')
            ->leftJoin(AclRolePermission::MODEL_NAME . ' rp', 'rp.permission_id=p.id')
            ->leftJoin(AclRole::MODEL_NAME . ' r', 'rp.role_id=r.id')
            ->leftJoin(AclUserRole::MODEL_NAME . ' ur', 'ur.role_id=r.id')
            ->field('r.id,r.data_scope')
            ->where([
                ['ur.user_id', '=', $userId],
                ['p.perms', 'LIKE', "%{$node}%"],
                ['p.status', '=', AclPermission::ENABLE],
                ['r.status', '=', AclRole::ENABLE],
            ])->order('r.data_scope', 'asc')
            ->select()->toArray();
    }
}
